createProductDocument
- ๐ฌ๐ง English
- ๐ฎ๐น Italian
Function Names: createOrUpdateProductDocument / createOrUpdateProductDocumentWithCatalogRef
Author: Domenico Cerone Creation Date: 25/09/2025
Last Reviewer: Domenico Cerone
Trigger: Called by populateVariantFromSku and populateVariantFromExcel
Purpose: Manages creation and updating of documents in the 'Products' Firestore collection from mapped JSON data and variant information. Handles the complete product lifecycle with automatic tag aggregation, brand management, and multi-language support.
Detailed Functionalityโ
This component function handles the complete Products collection management with a sophisticated 3-step workflow for both new products and existing product updates. Includes thread-safe tag creation system with mutex synchronization to prevent duplicates in high-concurrency scenarios.
1. PRODUCT EXISTENCE CHECKโ
- Searches in 'Products' collection for document with modelName equal to glassesName
- If EXISTS โ updates fields and adds/updates variant in variants_map (STEP 3)
- If NOT EXISTS โ creates new complete product document (STEP 2)
2. NEW PRODUCT CREATIONโ
- Creates document with complete base structure
- Populates fields from mapped JSON
- Creates variants_map with current variant
- Sets availableVariants = 0 (managed externally)
- Uses Firestore auto-generated ID
3. EXISTING PRODUCT UPDATEโ
- Updates product fields from mapped JSON
- Verifies if variant already exists in variants_map
- If variant doesn't exist โ adds new entry
- If variant exists โ updates existing entry
- Updates availableVariants with real count
- Updates list_frame_color_tags, list_size_tags, etc.
Fields Populated from Mapped JSONโ
Base Product Fieldsโ
- modelName โ glassesName (main identifier)
- age โ catAgeForGender
- manufacturedProductStatus โ manufacturedProductStatus
- rxAble โ rxAble (converted from "YES"/"NO" to boolean true/false)
- mainBrandRef โ Brand ID (find/create in MainBrands collection)
Image Fields (from current variant)โ
- imgUrl โ poster
- thumbnail โ poster
- urlImage โ poster
Timestamp Fieldsโ
- lastUpdate โ current timestamp (always updated, Date object)
- productReleaseDate โ productReleaseDate (if present in mapped JSON, Date object)
- productEndDate โ productEndDate (if present in mapped JSON, Date object)
Multi-language Descriptionsโ
- descriptionEn โ description_en
- descriptionIt โ description_it
- descriptionEs โ description_es
- descriptionFr โ description_fr
- descriptionDe โ description_de
Tag Arrays (aggregated from all variants)โ
- list_frame_color_tags โ [frameColor tag IDs from all product variants]
- list_size_tags โ [size tag IDs from all product variants]
- list_line_tags โ [line tag IDs]
- list_tags โ [catType, catAgeForGender, catGender, catForma, catMaterialOne, polarised, catLensesTreat, hingeType as tag IDs]
Variant Managementโ
- variants_map โ array with entry for each product variant:
- eanCode, id, publishedInARSLibrary (""), skuCode, upcCode, variantName (glassesName)
- list_variants โ [IDs of all product variants]
- availableVariants โ always 0 (logic managed externally)
Tag Aggregation Logicโ
Tags are intelligently aggregated from all existing variants belonging to the same product:
Frame Color Tagsโ
- For each frameColor creates/finds document in Tags collection
- Documents have: group="Frame Color", name="COLOR", type="frameColor"
- IDs aggregated for all product variants
Size Tagsโ
- For each size creates/finds document in Tags collection
- Documents have: group="Size", name="SIZE", type="size"
- IDs aggregated for all product variants
Line Tagsโ
- For each line name creates/finds document in Tags collection
- Documents have: catalogRef="BRAND_ID", group="Line", name="LINE", type="line"
- ID used (unique per product since line name doesn't change between variants)
Category Tags (list_tags)โ
Advanced tag system with automatic translations:
- catType โ Tag ID with: group="Tipologia", name=catType value, type="tag"
- catAgeForGender โ Tag ID with: group="Age For Gender", name=catAgeForGender value, type="categoria"
- catGender โ Tag ID with: group="Gender", name=translated catGender, type="categoria"
- "WOMAN" โ translated to "Donna"
- "MAN" โ translated to "Uomo"
- Other values remain unchanged
- catForma โ Tag ID with: group="Forma", name=catForma value, type="tag"
- catMaterialOne โ Tag ID with: group="Materiale", name=catMaterialOne value, type="tag"
- polarised โ Tag ID based on value:
- "YES" โ group="Polarised", name="POLARIZED", type="tag"
- "NO" โ group="Polarised", name="NO POLARIZED", type="tag"
- catLensesTreat โ Tag ID with: group="Treatement", name=catLensesTreat value, type="tag"
- hingeType โ Tag ID with: group="Hinge Type", name=hingeType value, type="tag"
Brand Normalizationโ
The mainBrandRef field is automatically normalized according to business rules:
- Hugo brands: "HUGO" โ "HUGO EYEWEAR"
- Boss brands: "HUGO BOSS", "BOSS ORANGE" โ "BOSS EYEWEAR"
- Carrera brands: "CARRERA BY JIMMYCHOO", "CARRERA BIKE", "CARRERA SNOW", "CARRERA DUCATI" โ "CARRERA"
- Polaroid brands: "POLAROID ANCILLARIES", "POLAROID KIDS", "POLAROID STAYSAFE" โ "POLAROID"
- Smith brands: "SMITH FASHION & ACC.", "SMITH BIKE HELMETS", "SMITH SNOW", "SMITH BIKE GOGGLES", "PRIVATE LABEL SMITH", "SUNCLOUD" โ "SMITH OPTICS"
- Other brands remain unchanged
Variants Map Structureโ
Each entry in variants_map contains:
- eanCode โ variant's eanCode (stored at variant level only)
- id โ variant document ID
- publishedInARSLibrary โ empty timestamp (future management)
- skuCode โ variant's skuModel
- upcCode โ variant's upcCode (stored at variant level only)
- variantName โ glassesName
Function Parametersโ
createOrUpdateProductDocumentโ
/**
* @param {Object} mappedJsonData - Mapped JSON data from populateVariantFromSku
* @param {string} variantDocumentId - ID of created/updated Variants document
* @param {string} requestId - Request ID for logging
* @returns {Promise<Object>} Operation result with details
*/
createOrUpdateProductDocumentWithCatalogRefโ
/**
* @param {Object} mappedJsonData - Mapped JSON data from populateVariantFromSku
* @param {string} variantDocumentId - ID of created/updated Variants document
* @param {string} requestId - Request ID for logging
* @param {string} catalogOrderId - CatalogOrder ID (optional)
* @returns {Promise<Object>} Operation result with details
*/
Response Structureโ
Success Responseโ
{
"operation": "create",
"documentId": "auto_generated_product_id",
"modelName": "TOMMY HILFIGER TH 1950/G",
"variantsCount": 0,
"success": true,
"message": "New Products document created for model TOMMY HILFIGER TH 1950/G"
}
Error Responseโ
{
"operation": "error",
"documentId": null,
"modelName": "TOMMY HILFIGER TH 1950/G",
"variantsCount": 0,
"success": false,
"message": "Error in Products document management: Missing glassesName",
"error": "Missing glassesName in mapped data - required for modelName"
}
Default Field Valuesโ
All other fields maintain default values:
- glassesCode: ""
- glassesInclinationCoeff: ""
- glassesInclinationCoeffIos: ""
- glassesYCoeff: ""
- glassesYCoeffAndroid: ""
- glassesZCoeff: ""
- glassesZCoeffAndroid: ""
- logLoadingModel: ""
- multiple3dViewerLink: ""
- notesNumber: 0
- priority: 0
- status: "Incompleto"
- urlProduct: ""
- urlShadow: ""
Thread-Safe Tag Management Systemโ
The function implements a sophisticated thread-safe tag creation system to prevent duplicate tags when processing multiple products simultaneously.
Tag Creation Functionsโ
Brand Management:
findOrCreateMainBrand()- Thread-safe brand creation with normalization- Automatically normalizes brand names according to business rules
- Prevents duplicate MainBrands documents in high-concurrency scenarios
Tag Creation (Thread-Safe):
findOrCreateFrameColorTag()- Frame color tags with group="Frame Color", type="frameColor" โ CallsfindOrCreateTagThreadSafe()from tagUtilsfindOrCreateSizeTag()- Size tags with group="Size", type="size" โ CallsfindOrCreateTagThreadSafe()from tagUtilsfindOrCreateLineTag()- Line tags with group="Line", type="line", catalogRef=brandId โ CallsfindOrCreateTagThreadSafe()from tagUtilsfindOrCreateCatTypeTag()- Category tags with group="Tipologia", type="tag" โ CallsfindOrCreateTagThreadSafe()from tagUtilsfindOrCreateCatGenderTag()- Gender tags with group="Gender", type="categoria" (with translation: WOMANโDonna, MANโUomo) โ CallsfindOrCreateTagThreadSafe()from tagUtilsfindOrCreateCatFormaTag()- Shape tags with group="Forma", type="tag" โ CallsfindOrCreateTagThreadSafe()from tagUtilsfindOrCreateCatMaterialOneTag()- Material tags with group="Materiale", type="tag" โ CallsfindOrCreateTagThreadSafe()from tagUtilsfindOrCreatePolarisedTag()- Polarization tags with group="Polarised", type="tag" (YESโPOLARIZED, NOโNO POLARIZED) โ CallsfindOrCreateTagThreadSafe()from tagUtilsfindOrCreateCatLensesTreatTag()- Lens treatment tags with group="Treatement", type="tag" โ CallsfindOrCreateTagThreadSafe()from tagUtilsfindOrCreateHingeTypeTag()- Hinge type tags with group="Hinge Type", type="tag" โ CallsfindOrCreateTagThreadSafe()from tagUtilsfindOrCreateCatAgeForGenderTag()- Age for gender tags with group="Age For Gender", type="categoria" โ CallsfindOrCreateTagThreadSafe()from tagUtils
Mutex Synchronization Systemโ
Problem Solved: When multiple products with the same tag values are processed in parallel, they could attempt to create the same Tags document simultaneously, leading to duplicates.
Solution: Thread-safe tag creation using findOrCreateTagThreadSafe():
- Lock Acquisition: Before creating a tag, acquires exclusive lock using tag name + group + type as key
- Lock Key Format:
TAG_CREATE_{group}_{type}_{name} - Polling Mechanism: If lock is held, waits with exponential backoff (50ms โ 1000ms max)
- Automatic Cleanup: Expired locks (older than 10 minutes) are automatically cleaned up
- Granular Locking: Each unique tag combination has its own lock
- Error Safety: Locks are released in finally blocks to ensure cleanup
Benefits:
- Prevents duplicate Tags documents
- Maintains tag consistency across collections
- Optimizes performance in batch processing scenarios
- Provides automatic recovery from stuck locks
Related Functionsโ
- populateVariantFromSku - Main workflow function that calls this component
- createVariantDocument - Manages Variants collection alongside this function
- tagUtils - Provides thread-safe tag creation utilities with mutex synchronization
Function Names: createOrUpdateProductDocument / createOrUpdateProductDocumentWithCatalogRef
Autore: Domenico Cerone Data di creazione: 25/09/2025
Last Reviewer: Domenico Cerone
Trigger: Chiamata da populateVariantFromSku e populateVariantFromExcel
Purpose: Gestisce la creazione e l'aggiornamento dei documenti nella collezione Firestore 'Products' a partire dai dati JSON mappati e dalle informazioni delle varianti. Gestisce il ciclo di vita completo del prodotto con aggregazione automatica dei tag, gestione brand e supporto multilingua.
Funzionamento Dettagliatoโ
Questa funzione componente gestisce la gestione completa della collezione Products con un sofisticato workflow di 3 step sia per prodotti nuovi che per aggiornamenti di prodotti esistenti. Include sistema di creazione tag thread-safe con sincronizzazione mutex per prevenire duplicati in scenari di alta concorrenza.
1. CONTROLLO ESISTENZA PRODOTTOโ
- Cerca nella collezione 'Products' un documento con modelName uguale a glassesName
- Se ESISTE โ aggiorna i campi e aggiungi/aggiorna variante in variants_map (STEP 3)
- Se NON ESISTE โ crea nuovo documento prodotto completo (STEP 2)
2. CREAZIONE NUOVO PRODOTTOโ
- Crea documento con struttura base completa
- Popola campi dal JSON mappato
- Crea variants_map con la variante corrente
- Imposta availableVariants = 0 (gestito esternamente)
- Utilizza ID auto-generato di Firestore
3. AGGIORNAMENTO PRODOTTO ESISTENTEโ
- Aggiorna campi del prodotto dal JSON mappato
- Verifica se la variante esiste giร in variants_map
- Se variante non esiste โ aggiunge nuova entry
- Se variante esiste โ aggiorna entry esistente
- Aggiorna availableVariants con conteggio reale
- Aggiorna list_frame_color_tags, list_size_tags, etc.
Campi Popolati dal JSON Mappatoโ
Campi Base Prodottoโ
- modelName โ glassesName (identificatore principale)
- age โ catAgeForGender
- manufacturedProductStatus โ manufacturedProductStatus
- rxAble โ rxAble (convertito da "YES"/"NO" a boolean true/false)
- mainBrandRef โ ID brand (cerca/crea in collezione MainBrands)
Campi Immagini (dalla variante corrente)โ
- imgUrl โ poster
- thumbnail โ poster
- urlImage โ poster
Campi Timestampโ
- lastUpdate โ timestamp corrente (sempre aggiornato, oggetto Date)
- productReleaseDate โ productReleaseDate (se presente nel JSON mappato, oggetto Date)
- productEndDate โ productEndDate (se presente nel JSON mappato, oggetto Date)
Descrizioni Multilinguaโ
- descriptionEn โ description_en
- descriptionIt โ description_it
- descriptionEs โ description_es
- descriptionFr โ description_fr
- descriptionDe โ description_de
Array Tags (aggregati da tutte le varianti)โ
- list_frame_color_tags โ [ID tag frameColor da tutte le varianti del prodotto]
- list_size_tags โ [ID tag size da tutte le varianti del prodotto]
- list_line_tags โ [ID tag line]
- list_tags โ [catType, catAgeForGender, catGender, catForma, catMaterialOne, polarised, catLensesTreat, hingeType come ID tag]
Gestione Variantiโ
- variants_map โ array con entry per ogni variante del prodotto:
- eanCode, id, publishedInARSLibrary (""), skuCode, upcCode, variantName (glassesName)
- list_variants โ [ID di tutte le varianti del prodotto]
- availableVariants โ sempre 0 (logica gestita esternamente)
Logica Aggregazione Tagsโ
I tag vengono aggregati intelligentemente da tutte le varianti esistenti appartenenti allo stesso prodotto:
Tag Colore Frameโ
- Per ogni frameColor crea/trova documento nella collezione Tags
- I documenti hanno: group="Frame Color", name="COLORE", type="frameColor"
- ID aggregati per tutte le varianti del prodotto
Tag Sizeโ
- Per ogni size crea/trova documento nella collezione Tags
- I documenti hanno: group="Size", name="TAGLIA", type="size"
- ID aggregati per tutte le varianti del prodotto
Tag Lineโ
- Per ogni nome linea crea/trova documento nella collezione Tags
- I documenti hanno: catalogRef="BRAND_ID", group="Line", name="LINEA", type="line"
- ID utilizzato (unico per prodotto dato che nome linea non cambia tra varianti)
Tag Categoria (list_tags)โ
Sistema di tag avanzato con traduzioni automatiche:
- catType โ ID Tag con: group="Tipologia", name=valore catType, type="tag"
- catAgeForGender โ ID Tag con: group="Age For Gender", name=valore catAgeForGender, type="categoria"
- catGender โ ID Tag con: group="Gender", name=traduzione catGender, type="categoria"
- "WOMAN" โ tradotto in "Donna"
- "MAN" โ tradotto in "Uomo"
- Altri valori rimangono invariati
- catForma โ ID Tag con: group="Forma", name=valore catForma, type="tag"
- catMaterialOne โ ID Tag con: group="Materiale", name=valore catMaterialOne, type="tag"
- polarised โ ID Tag basato sul valore:
- "YES" โ group="Polarised", name="POLARIZED", type="tag"
- "NO" โ group="Polarised", name="NO POLARIZED", type="tag"
- catLensesTreat โ ID Tag con: group="Treatement", name=valore catLensesTreat, type="tag"
- hingeType โ ID Tag con: group="Hinge Type", name=valore hingeType, type="tag"
Normalizzazione Brandโ
Il campo mainBrandRef viene automaticamente normalizzato secondo le regole di business:
- Brand Hugo: "HUGO" โ "HUGO EYEWEAR"
- Brand Boss: "HUGO BOSS", "BOSS ORANGE" โ "BOSS EYEWEAR"
- Brand Carrera: "CARRERA BY JIMMYCHOO", "CARRERA BIKE", "CARRERA SNOW", "CARRERA DUCATI" โ "CARRERA"
- Brand Polaroid: "POLAROID ANCILLARIES", "POLAROID KIDS", "POLAROID STAYSAFE" โ "POLAROID"
- Brand Smith: "SMITH FASHION & ACC.", "SMITH BIKE HELMETS", "SMITH SNOW", "SMITH BIKE GOGGLES", "PRIVATE LABEL SMITH", "SUNCLOUD" โ "SMITH OPTICS"
- Altri brand rimangono invariati
Struttura Variants Mapโ
Ogni entry in variants_map contiene:
- eanCode โ eanCode della variante (memorizzato solo a livello variante)
- id โ ID documento della variante
- publishedInARSLibrary โ timestamp vuoto (gestione futura)
- skuCode โ skuModel della variante
- upcCode โ upcCode della variante (memorizzato solo a livello variante)
- variantName โ glassesName
Parametri Funzioneโ
createOrUpdateProductDocumentโ
/**
* @param {Object} mappedJsonData - Dati JSON mappati da populateVariantFromSku
* @param {string} variantDocumentId - ID del documento Variants creato/aggiornato
* @param {string} requestId - ID della richiesta per logging
* @returns {Promise<Object>} Risultato dell'operazione con dettagli
*/
createOrUpdateProductDocumentWithCatalogRefโ
/**
* @param {Object} mappedJsonData - Dati JSON mappati da populateVariantFromSku
* @param {string} variantDocumentId - ID del documento Variants creato/aggiornato
* @param {string} requestId - ID della richiesta per logging
* @param {string} catalogOrderId - ID del CatalogOrder (opzionale)
* @returns {Promise<Object>} Risultato dell'operazione con dettagli
*/
Struttura Responseโ
Response Successoโ
{
"operation": "create",
"documentId": "auto_generated_product_id",
"modelName": "TOMMY HILFIGER TH 1950/G",
"variantsCount": 0,
"success": true,
"message": "Nuovo documento Products creato per modello TOMMY HILFIGER TH 1950/G"
}
Response Erroreโ
{
"operation": "error",
"documentId": null,
"modelName": "TOMMY HILFIGER TH 1950/G",
"variantsCount": 0,
"success": false,
"message": "Errore nella gestione documento Products: glassesName mancante",
"error": "glassesName mancante nei dati mappati - necessario per modelName"
}
Valori Campi di Defaultโ
Tutti gli altri campi mantengono i valori di default:
- glassesCode: ""
- glassesInclinationCoeff: ""
- glassesInclinationCoeffIos: ""
- glassesYCoeff: ""
- glassesYCoeffAndroid: ""
- glassesZCoeff: ""
- glassesZCoeffAndroid: ""
- logLoadingModel: ""
- multiple3dViewerLink: ""
- notesNumber: 0
- priority: 0
- status: "Incompleto"
- urlProduct: ""
- urlShadow: ""
Sistema di Gestione Tag Thread-Safeโ
La funzione implementa un sistema sofisticato di creazione tag thread-safe per prevenire tag duplicati quando si processano piรน prodotti simultaneamente.
Funzioni di Creazione Tagโ
Gestione Brand:
findOrCreateMainBrand()- Creazione brand thread-safe con normalizzazione- Normalizza automaticamente i nomi brand secondo regole di business
- Previene documenti MainBrands duplicati in scenari di alta concorrenza
Creazione Tag (Thread-Safe):
findOrCreateFrameColorTag()- Tag colore frame con group="Frame Color", type="frameColor" โ ChiamafindOrCreateTagThreadSafe()da tagUtilsfindOrCreateSizeTag()- Tag taglie con group="Size", type="size" โ ChiamafindOrCreateTagThreadSafe()da tagUtilsfindOrCreateLineTag()- Tag linee con group="Line", type="line", catalogRef=brandId โ ChiamafindOrCreateTagThreadSafe()da tagUtilsfindOrCreateCatTypeTag()- Tag categoria con group="Tipologia", type="tag" โ ChiamafindOrCreateTagThreadSafe()da tagUtilsfindOrCreateCatGenderTag()- Tag genere con group="Gender", type="categoria" (con traduzione: WOMANโDonna, MANโUomo) โ ChiamafindOrCreateTagThreadSafe()da tagUtilsfindOrCreateCatFormaTag()- Tag forma con group="Forma", type="tag" โ ChiamafindOrCreateTagThreadSafe()da tagUtilsfindOrCreateCatMaterialOneTag()- Tag materiale con group="Materiale", type="tag" โ ChiamafindOrCreateTagThreadSafe()da tagUtilsfindOrCreatePolarisedTag()- Tag polarizzazione con group="Polarised", type="tag" (YESโPOLARIZED, NOโNO POLARIZED) โ ChiamafindOrCreateTagThreadSafe()da tagUtilsfindOrCreateCatLensesTreatTag()- Tag trattamento lenti con group="Treatement", type="tag" โ ChiamafindOrCreateTagThreadSafe()da tagUtilsfindOrCreateHingeTypeTag()- Tag tipo cerniera con group="Hinge Type", type="tag" โ ChiamafindOrCreateTagThreadSafe()da tagUtilsfindOrCreateCatAgeForGenderTag()- Tag etร per genere con group="Age For Gender", type="categoria" โ ChiamafindOrCreateTagThreadSafe()da tagUtils
Sistema Mutex Sincronizzazioneโ
Problema Risolto: Quando piรน prodotti con gli stessi valori tag vengono processati in parallelo, potrebbero tentare di creare lo stesso documento Tags simultaneamente, causando duplicati.
Soluzione: Creazione tag thread-safe usando findOrCreateTagThreadSafe():
- Acquisizione Lock: Prima di creare un tag, acquisisce lock esclusivo usando nome tag + group + type come chiave
- Formato Chiave Lock:
TAG_CREATE_{group}_{type}_{name} - Meccanismo Polling: Se il lock รจ detenuto, attende con backoff esponenziale (50ms โ 1000ms max)
- Cleanup Automatico: Lock scaduti (piรน vecchi di 10 minuti) vengono automaticamente puliti
- Locking Granulare: Ogni combinazione tag unica ha il suo lock
- Sicurezza Errori: I lock vengono rilasciati nei blocchi finally per garantire cleanup
Vantaggi:
- Previene documenti Tags duplicati
- Mantiene consistenza tag tra collezioni
- Ottimizza performance in scenari di batch processing
- Fornisce recovery automatico da lock bloccati
Funzioni Correlateโ
- populateVariantFromSku - Funzione workflow principale che chiama questo componente
- createVariantDocument - Gestisce la collezione Variants insieme a questa funzione
- tagUtils - Fornisce utilitร per creazione tag thread-safe con sincronizzazione mutex